home *** CD-ROM | disk | FTP | other *** search
- program Query;
- { This program allows variables in the COMMAND environment area to be
- redefined interactivly. Its primary use is in .BAT files. Due to the
- way COMMAND allocates the environment segment is isn't easy to
- create new variables or increase the length of the value of old ones.
- Therefore the variable to be set by query MUST be initialized to a string
- of its largest legal size before executing QUERY.
-
- Syntax:
- QUERY [/R][/Y][/N][/U][/n1,n2] <varname> [<string>..[<string>]]
-
- Example of Usage:
- SET ANSWER=*
- QUERY /Y ANSWER Do you want to delete all backup files?
- IF %ANSWER%==Y GOTO DELETEM
- GOTO EXIT
- SET FILE=*************
- QUERY FILE Enter the file name.ext:
-
- Options:
- /R Response is required
- /Y Response must be either Y or N.
- /N Response must be an integer
- /<n1>[,<n2>] Response must be an integer range 1 ..<n1> or <n1>..<n2>
- /U Convert response to upper case
- }
-
- type
- EnvBuff = record
- Env: array[1..2048] of char;
- end;
- EnvironmentPointer = ^EnvBuff;
- Str4 = string[4];
- str8 = string[8];
- str9 = string[9];
- str32 = string[32];
- str64 = string[132];
-
- var
- EnvPtr,SearchPtr: EnvironmentPointer;
- FirstChar, LastChar,
- Index, VarLen, StringLen,
- BufferLen, ParamIndex,Ival,
- Source, Target, Count,
- HighRange,LowRange,Col: integer;
- Setname,VarName,Option: Str32;
- NewVal: Str64;
- EndOfEnv,Found,InOptions,
- Yoption,Noption,Uoption,
- Roption, RangeOption,
- LegalResponse: boolean;
-
- begin
- If ParamCount > 0 then
- begin
- ParamIndex := 0;
- InOptions := True;
- Yoption := false;
- Noption := false;
- Uoption := false;
- Roption := false;
- RangeOption := false;
-
- Repeat
- begin
- ParamIndex := ParamIndex + 1;
- If ParamIndex > ParamCount then InOptions := False;
- Option := ParamStr(ParamIndex);
- If Option[1] = '/' then
- begin
- Index := 1;
- While Index <= Length(Option) do
- begin
- If Option[Index] <> '/' then
- Writeln('Error, options must be seperated by "/"s');
- Index := Index + 1;
- Case UpCase(Option[Index]) of
- '/': ;
- 'Y': Yoption := true;
- 'N': Noption := true;
- 'U': Uoption := true;
- 'R': Roption := true;
- '0'..'9': begin
- RangeOption := true;
- LowRange := 1;
- HighRange := 0;
- While ( (Option[Index] >= '0') and (Option[Index] <= '9') ) and
- (Index <= Length(Option)) do
- begin
- HighRange := 10*HighRange + ( Ord(Option[Index])-Ord('0'));
- Index := Index + 1;
- end;
- If Option[Index] = ',' then
- begin
- Index := Index + 1;
- LowRange := HighRange;
- HighRange := 0;
- While ( (Option[Index] >= '0') and (Option[Index] <= '9') ) and
- (Index <= Length(Option)) do
- begin
- HighRange := 10*HighRange + ( Ord(Option[Index])-Ord('0'));
- Index := Index + 1;
- end;
- end;
- If Index < Length(Option) then Index := Index - 1;
- end {RangeOption};
- Else Writeln('Invalid option:',Option[Index]);
- end {Case};
- Index := Index + 1;
- end;
- end
- Else
- InOptions := false;
- end;
- Until not InOptions;
-
-
-
- { Get the variable name from the parameter field and convert it to
- upper case as COMMAND does. }
- VarName := ParamStr(ParamIndex);
- For Index := 1 to Length(VarName) do
- VarName[Index] := UpCase(VarName[Index]);
-
- { Set up addressing so that the Env array is based in the segment the
- command processor is using for variables. The command processor leaves a
- pointer to a copy of the environment area in CS:2C }
- MemW[ Seg(EnvPtr):Ofs(EnvPtr)+2 ] := MemW[Cseg:$002C];
- MemW[ Seg(EnvPtr):Ofs(EnvPtr) ] := 0;
- BufferLen := 0;
- Repeat BufferLen := BufferLen + 1 Until EnvPtr^.Env[BufferLen] = #$01;
-
- { Search through memory for the REAL environment area. This will be
- identical to the copy COMMAND provided us. This search is pretty quick
- because command allocates program memory against its memory. }
- Found := False;
- SearchPtr := EnvPtr;
- Repeat
- begin
- MemW[Seg(SearchPtr):Ofs(SearchPtr)+2] :=
- MemW[Seg(SearchPtr):Ofs(SearchPtr)+2] - 1;
- Col := 0;
- Repeat Col := Col + 1;
- Until (Col = BufferLen) or (EnvPtr^.Env[Col] <> SearchPtr^.Env[Col]);
- If Col = BufferLen then Found := True;
- end;
- Until Found or (MemW[Seg(SearchPtr):Ofs(SearchPtr)+2] = $0000);
- If Not Found then
- begin
- Writeln;
- Writeln('COMMAND processor environment area not found in memory');
- Halt;
- end
- Else
- EnvPtr := SearchPtr;
-
-
-
-
- With EnvPtr^ do
- begin
- Index := 1;
- EndOfEnv := Env[1]=#$01;
- EndOfEnv := False;
- Found := False;
-
- { Scan the environment area for this variable name. Format expected here
- is the variable name (in upper case) followed by an '=' then a
- string terminated by and #$00 (ASCIIZ). Then end of environment is
- indicated by a SOH (#$01) where variable name should begin. }
- While not EndOfEnv and not Found do
- begin
- Setname := '';
- While ( Env[Index] <> '=' ) and ( Env[Index] <> #$00 ) do
- begin
- Setname := Setname + Env[Index];
- Index := Index + 1;
- end;
-
- If SetName = VarName then
- Found := true
- Else { skip this variables value }
- Repeat Index := Index + 1 Until Env[Index] = #$00;
-
- Index := Index + 1;
- EndOfEnv := Env[Index] = #$01;
- If EndOfEnv then
- Writeln('Error:',Varname,' must be SET before using query');
- end;
-
- If Found then
- begin
- FirstChar := Index;
- Repeat Index := Index + 1 Until Env[Index] = #$00;
- LastChar := Index - 1;
- StringLen := LastChar-FirstChar+1;
-
- LegalResponse := false;
- Repeat
- begin
- Index := ParamIndex+1;
- While Index <= ParamCount do
- begin
- Write(ParamStr(Index),' ');
- Index := Index + 1;
- end;
- Read(NewVal);
- If Uoption or Yoption then For Col := 1 to Length(NewVal) do
- NewVal[Col] := UpCase(NewVal[Col]);
- LegalResponse := True;
-
- If Yoption then
- begin
- If Length(NewVal) > 0 then NewVal := NewVal[1];
- If ( NewVal <> 'N' ) and ( NewVal <> 'Y' ) then
- begin
- Writeln;
- Writeln('Answer either "YES" or "NO"');
- LegalResponse := False;
- end;
- end;
-
- If Noption then
- begin
- Col := 1;
- While Col <= Length(NewVal) do
- If (NewVal[Col] > '9') or (NewVal[Col] < '0') then
- begin
- LegalResponse := False;
- Col := Length(NewVal)+1;
- Writeln;
- Write('Response should be a number');
- Writeln;
- end
- Else
- Col := Col + 1;
- end;
-
- If Roption and (Length(NewVal) = 0) then
- begin
- LegalResponse := False;
- Writeln;
- Writeln('A response is required');
- Writeln;
- end;
-
- If RangeOption then
- begin
- Ival := 0;
- Col := 1;
- While Col <= Length( NewVal ) do
- begin
- If ( Newval[Col] > '9' ) or ( NewVal[Col] < '0' ) then
- begin
- Col := Length( NewVal ) + 1;
- Writeln;
- Writeln('Response should be a number');
- Writeln;
- LegalResponse := False;
- end
- Else
- begin
- Ival := Ival*10 + ( Ord(NewVal[Col]) - Ord('0') );
- Col := Col + 1;
- end;
- end;
-
- If ( Ival > HighRange ) or ( Ival < LowRange ) then
- begin
- Writeln;
- Writeln('Answer must be in the range ',LowRange,'..',
- HighRange);
- Writeln;
- LegalResponse := False;
- end;
- end;
- end;
- Until LegalResponse;
-
- { Truncate the input string if it is too long }
- If Length(NewVal) > StringLen then NewVal := Copy(NewVal,1,StringLen);
- { Now copy the new value to the environment area }
- Col := 1;
- Index := FirstChar;
- While Col <= Length(NewVal) do
- begin
- Env[Index] := NewVal[Col];
- Col := Col + 1;
- Index := Index + 1;
- end;
- { If the new value is shorter that the string length then shift the
- rest of the environment area down }
- Count := BufferLen - LastChar - 1;
- Source := LastChar + 1;
- Target := Index;
- For Index := 1 to Count do
- begin
- Env[Target] := Env[Source];
- Source := Source + 1;
- Target := Target + 1;
- end;
- end;
- end;
- end;
- end.